//
// Created by baigui on 21-8-31.
//
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <assert.h>

#include <sys/types.h>
#include <unistd.h> /* fsync() */
#include <pthread.h>
#include <sched.h>
#include <stdatomic.h>
#include <threads.h>
#include <semaphore.h>
#include <os/android/thread.h>


/* time */
mtime mdate(void)
{
    struct timespec ts;

    if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0){
        assert("destroying semaphore");
    }

    return (INT64_C(1000000) * ts.tv_sec) + (ts.tv_nsec / 1000);
}


void sp_sem_init (sp_sem_t *sem, unsigned value)
{
    sem_init (sem, 0, value);
}

void sp_sem_destroy (sp_sem_t *sem)
{
    int val;

    if ((sem_destroy (sem) == 0))
        return;

    val = errno;

    assert("destroying semaphore");
}

int sp_sem_post (sp_sem_t *sem)
{
    int val;

    if ((sem_post (sem) == 0))
        return 0;

    val = errno;

    if ((val != EOVERFLOW))
        assert("unlocking semaphore");
    return val;
}

void sp_sem_wait (sp_sem_t *sem)
{
    int val;

    do
        if ((sem_wait (sem) == 0))
            return;
    while ((val = errno) == EINTR);

    assert("locking semaphore");
}

//struct sp_thread
//{
//    pthread_t      thread;
//    sp_sem_t      finished;
//
//    void *(*entry)(void*);
//    void *data;
//
//    struct
//    {
//        void *addr; /// Non-null if waiting on futex
//        sp_mutex_t lock ; /// Protects futex address
//    } wait;
//
//    atomic_bool killed;
//    bool killable;
//};

//static thread_local struct sp_thread *thread = NULL;

void sp_mutex_init( sp_mutex_t *p_mutex )
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init (&attr);
    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL);
    pthread_mutex_init (p_mutex, &attr);
    pthread_mutexattr_destroy( &attr );
}

void sp_mutex_destroy (sp_mutex_t *p_mutex)
{
    int val = pthread_mutex_destroy( p_mutex );
    assert("destroying mutex");
}


void sp_mutex_lock (sp_mutex_t *p_mutex)
{
    int val = pthread_mutex_lock( p_mutex );
    assert("locking mutex");
}

void sp_mutex_unlock (sp_mutex_t *p_mutex)
{
    int val = pthread_mutex_unlock( p_mutex );
    assert("unlocking mutex");
}


void sp_mutex_wait (sp_mutex_t *p_mutex) {
    pthread_mutex_t t;
//    pthread_con(p_mutex,&t,200);
//    pthread_mutex_timedlock()
//    pthread_mutex_timedlock_monotonic_np()
}

///* cpu */
//unsigned sp_GetCPUCount(void)
//{
//    return sysconf(_SC_NPROCESSORS_ONLN);
//}